home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / v7n13.arc / SETMODE.ASM < prev    next >
Assembly Source File  |  1988-07-01  |  27KB  |  967 lines

  1. ;======================================================================
  2. ; SETMODE is a resident program which allows you to set the video mode
  3. ; and the communication port protocol.  PC Magazine July, 1988
  4. ;----------------------------------------------------------------------
  5. ; BIOS_SEG is the ROM-BIOS data area
  6. ;----------------------------------------------------------------------
  7. BIOS_SEG    SEGMENT    AT 0040H
  8.         ORG    0010H
  9. EQUIP_FLAG    DW    ?
  10.         ORG    0049H
  11. CRT_MODE    DB    ?
  12. COLUMNS        DB    ?        ;Current number of columns
  13.         ORG    0050H
  14. CURSOR_POSN    DW    8 DUP(?)    ;Current cursor location
  15.         ORG    0062H
  16. ACTIVE_PAGE    DB    ?        ;Active page for CGA and EGA
  17.         ORG    0084H
  18. ROWS        DB    ?        ;Last row number for EGA
  19.         DW    ?
  20. EGA_INFO    DB    ?
  21. BIOS_SEG    ENDS
  22.  
  23. CSEG        SEGMENT
  24.         ASSUME    CS:CSEG, DS:CSEG, ES:CSEG
  25.         ORG    0100H        ;Beginning for .COM programs
  26. START:        JMP    INITIALIZE    ;Initialization code is at end
  27.  
  28. ;----------------------------------------------------------------------
  29. ; Data area used by this program
  30. ;----------------------------------------------------------------------
  31. HOTKEY        EQU    32H        ;Scan code for "M" key
  32. SHIFT_MASK    EQU    00001000B    ;Mask for ALT key
  33. CR        EQU    13
  34. LF        EQU    10
  35.  
  36. COPYRIGHT    DB    "SETMODE 1.0 (c) 1988 Ziff Communications Co."
  37.         DB    CR,LF,"PC Magazine ",254," Tom Kihlken"
  38.         DB    CR,LF,"Hotkey is Alt-M$",1AH
  39. INSTALLED_MSG    DB    CR,LF,"Already Installed$"
  40.  
  41. WINDOW_TEXT    DB    2, 1,"SETMODE 1.0   "
  42.         DB    24,32,25,32,26,32,27," + -  <CR> Esc",0
  43.         DB    4, 4,"COMMUNICATION PORTS",0
  44.         DB    2, 5,"Port:",0
  45.         DB    16,5,"1",0
  46.         DB    23,5,"2",0
  47.         DB    30,5,"3",0
  48.         DB    37,5,"4",0
  49.         DB    2, 6,"Bps:",0
  50.         DB    2, 7,"Parity:",0
  51.         DB    2, 8,"Data bits:",0
  52.         DB    2, 9,"Stop Bits:",0
  53.         DB    2,10,"DSR:",0
  54.         DB    4,13,"DISPLAY",0
  55.         DB    4,14,"Mode:",0
  56.         DB    2,15,"0 1 2 3 4 5 6 7 13 14 15 16 17 18 19",0,0
  57.  
  58. COUNTER1    DB    ?
  59. COUNTER2    DB    ?
  60. BUSY_FLAG    DB    0
  61. COLORS        LABEL    WORD
  62. NORMAL        DB    ?
  63. INVERSE        DB    ?
  64. OLDINT09    DD    ?
  65. LEFT_SIDE    DB    ?
  66. MODE_SELECT    DB    ?
  67. GRAPH_TEXT    DB    ?
  68. ITEM_SELECT    DB    0
  69. PORT_SELECT    DB    0
  70. PORT_ADDRESS    DW    ?
  71. ADAPTER_FLAGS    DB    ?
  72. ADAPTER_TABLE    DB    54,54,54,54,54,54,54,25,00,00,00,00,00,20,20
  73.         DB    24,20,48,16,48
  74. EQUIP_TABLE    DB    16,16,32,32,32,32,32,48,00,00,00,00,00,16,16
  75.         DB    48,16,32,32,32
  76.  
  77. ;----------------------------------------------------------------------
  78. ; This is the main routine of the resident portion of the code
  79. ;----------------------------------------------------------------------
  80. SETMODE        PROC    NEAR
  81.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  82.         CALL    GET_CURS_ADDR    ;Cursor address for this page
  83.         PUSH    ES:[BX]        ;Save the cursor location
  84.         MOV    AL,ES:CRT_MODE    ;Get current mode
  85.         AND    AL,01111111B    ;Mask the high bit
  86.         MOV    MODE_SELECT,AL    ;Store the initial video mode
  87.  
  88.         MOV    GRAPH_TEXT,1
  89.         MOV    BX,7007H    ;Colors for mono mode
  90.         CMP    AL,07H        ;In mono text mode?
  91.         JE    NOT_COLOR_TEXT
  92.         MOV    BX,0503H    ;Colors for graphics modes
  93.         MOV    GRAPH_TEXT,0
  94.         CMP    AL,3        ;In CGA text mode?
  95.         JA    NOT_COLOR_TEXT
  96.         MOV    GRAPH_TEXT,1
  97.         MOV    BH,ES:ACTIVE_PAGE
  98.         MOV    AH,8        ;Read current colors
  99.         INT    10H        ;BIOS read char/attribute
  100.         MOV    BL,AH        ;Foreground color
  101.         MOV    BH,AH        ;Background color
  102.         XOR    BH,1110111B    ;Flip the color bits
  103. NOT_COLOR_TEXT:
  104.         MOV    COLORS,BX
  105.         MOV    DI,OFFSET WINDOW_BUFFER
  106.         MOV    DL,ES:COLUMNS    ;Compute center of screen
  107.         SUB    DL,40        ;We'll use 40 columns
  108.         SHR    DL,1        ;Divide by two
  109.         MOV    LEFT_SIDE,DL    ;This is column for left edge
  110.  
  111.         XOR    DH,DH        ;First window in row 0
  112.         MOV    COUNTER1,1
  113.         CALL    OPEN_WINDOW    ;Open top window
  114.         MOV    COUNTER1,6
  115.         CALL    OPEN_WINDOW    ;Open middle window
  116.         MOV    COUNTER1,3
  117.         CALL    OPEN_WINDOW    ;Open bottom window
  118.         MOV    SI,OFFSET WINDOW_TEXT
  119. TEXT_LOOP:
  120.         LODSW            ;Fill in window text
  121.         OR    AL,AL
  122.         JZ    TEXT_DONE    ;Is this the last string yet?
  123.         MOV    DX,AX        ;Get row/column for this string
  124.         ADD    DL,LEFT_SIDE    ;Add in left edge of window
  125.         CALL    TTY_STRING    ;Put up the string
  126.         JMP    TEXT_LOOP    ;Loop for all text strings
  127. TEXT_DONE:
  128.         CMP    ES:CRT_MODE,19    ;Is this mode 0-19?
  129.         JA    GET_A_KEY    ;If not, can't point to it
  130.         CALL    VIDEO_COLUMN    ;Get column for current mode
  131.         INC    DL
  132.         MOV    DH,16
  133.         MOV    AL,30        ;ASCII for up carrot
  134.         CALL    DISPLAY_NORMAL    ;Pointer to current mode
  135. GET_A_KEY:
  136.         CALL    SHOW_PORTS    ;Display comm port status
  137.         CALL    SHOW_MODE    ;Display video info
  138.         MOV    CH,INVERSE
  139.         CALL    REV_BAR        ;Inverse video for selected item
  140.         XOR    AH,AH
  141.         INT    16H        ;Read a keystroke
  142.         PUSH    AX        ;Save the keystroke
  143.         MOV    CH,NORMAL
  144.         CALL    REV_BAR        ;Turn off reverse bar
  145.         POP    AX        ;Get back the keystroke
  146.  
  147.         CMP    AH,48H        ;Is it up arrow ?
  148.         JNE    NOT_UP
  149.         CMP    WORD PTR ES:[0000],0 ;Is there a COMM1?
  150.         JZ    GET_A_KEY    ;If not, don't go up
  151.         DEC    ITEM_SELECT    ;Move up to next item
  152.         JNS    GET_A_KEY
  153.         MOV    ITEM_SELECT,4
  154.         JMP    GET_A_KEY    ;And get another keystroke
  155. NOT_UP:
  156.         CMP    AH,50H        ;Is it down arrow?
  157.         JNE    NOT_DOWN
  158.         INC    ITEM_SELECT    ;Move down to next item
  159.         CMP    ITEM_SELECT,4
  160.         JBE    GET_A_KEY
  161.         MOV    ITEM_SELECT,0
  162.         JMP    GET_A_KEY
  163. NOT_DOWN:
  164.         CMP    AH,4DH        ;Is it right arrow?
  165.         JNE    NOT_RIGHT
  166.         MOV    AL,1        ;Indicate moving to right
  167.         CALL    SIDEWAYS    ;And move the bar
  168. NOT_RIGHT:
  169.         CMP    AH,4BH        ;Is it left arrow?
  170.         JNE    NOT_LEFT
  171.         MOV    AL,-1        ;Indicate moving to left
  172.         CALL    SIDEWAYS    ;And move the bar
  173. NOT_LEFT:
  174.         CMP    AL,"+"        ;Is it the plus key?
  175.         JNE    NOT_PLUS
  176.         MOV    CL,1        ;Indicate increasing value
  177.         JMP    CHG_COMM
  178. NOT_PLUS:
  179.         CMP    AL,"-"        ;Is it the minus key?
  180.         JNE    NOT_MINUS
  181.         MOV    CL,-1        ;Indicate decrease value
  182.         JMP    CHG_COMM
  183. NOT_MINUS:
  184.         CMP    AH,1        ;Is it escape?
  185.         JE    ESC_OUT
  186.         CMP    AL,13        ;Is it carriage return?
  187.         JE    EXIT_OUT
  188.         JMP    GET_A_KEY    ;Ignore any other keys
  189. ESC_OUT:
  190.         MOV    AL,ES:CRT_MODE    ;Get starting video mode
  191.         MOV    MODE_SELECT,AL    ;Make it the selected mode
  192. EXIT_OUT:
  193.         XOR    DH,DH        ;Restore the window
  194.         MOV    SI,OFFSET WINDOW_BUFFER
  195. ROW_LOOP:
  196.         MOV    CX,40        ;Do all 40 columns
  197.         MOV    DL,LEFT_SIDE
  198. COL_LOOP:
  199.         LODSW
  200.         CALL    DISPLAY_CHAR
  201.         LOOP    COL_LOOP    ;Loop for each column
  202.         INC    DH        ;Move to next row
  203.         CMP    DH,18
  204.         JNE    ROW_LOOP    ;Loop for each row
  205.         CALL    GET_CURS_ADDR    ;Get cursor address for this page
  206.         POP    ES:[BX]        ;Restore original cursor position
  207.  
  208.         MOV    BL,MODE_SELECT    ;Get starting video mode
  209.         CMP    BL,ES:CRT_MODE    ;Has it changed?
  210.         JE    SAME_MODE    ;If not, just return
  211.         XOR    BH,BH
  212.         MOV    CL,EQUIP_TABLE[BX]
  213.         MOV    AX,ES:EQUIP_FLAG
  214.         AND    AL,11001111B    ;Erase old video settings
  215.         OR    AL,CL        ;Set new video equipment bits
  216.         MOV    ES:EQUIP_FLAG,AX;Write new equipment word
  217.         MOV    AX,BX
  218.         INT    10H        ;Reinitialize video adapter
  219.         MOV    AH,2
  220.         XOR    DX,DX        ;Put cursor at home
  221.         XOR    BH,BH        ;For page zero
  222.         INT    10H        ;BIOS set cursor function
  223. SAME_MODE:
  224.         RET
  225. SETMODE        ENDP
  226.  
  227. ;----------------------------------------------------------------------
  228. ; Sideways moves the moving bar left and right
  229. ;----------------------------------------------------------------------
  230. SIDEWAYS    PROC    NEAR
  231.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  232.         CMP    ITEM_SELECT,0    ;Doing video modes?
  233.         JE    CHG_MODE    ;If yes then change the mode
  234.         MOV    BL,PORT_SELECT    ;Get comm port number
  235.         ADD    BL,AL        ;Move to next port
  236.         MOV    PORT_SELECT,BL
  237.         CMP    BL,3        ;Maximum of 3 ports
  238.         JA    SIDEWAYS
  239.  
  240.         XOR    BH,BH
  241.         SHL    BX,1
  242.         CMP    WORD PTR ES:[BX],0 ;Is there a card installed?
  243.         JZ    SIDEWAYS    ;If no card move to next
  244.         RET
  245. CHG_MODE:
  246.         CMP    ADAPTER_FLAGS,0
  247.         JE    UNKNOWN_ADAPTER
  248.         MOV    BL,MODE_SELECT    ;Get current mode
  249.         ADD    BL,AL        ;Move to next one
  250.         MOV    MODE_SELECT,BL
  251.         CMP    BL,19        ;Last mode is number 19
  252.         JA    CHG_MODE
  253.         XOR    BH,BH
  254.         MOV    CL,ADAPTER_TABLE[BX]
  255.         AND    CL,ADAPTER_FLAGS ;Is this adapter installed?
  256.         JZ    CHG_MODE    ;If not, use next mode
  257. UNKNOWN_ADAPTER:
  258.         RET
  259. SIDEWAYS    ENDP
  260.  
  261. ;----------------------------------------------------------------------
  262. ; CHG_COMM changes the parameters of the serial ports
  263. ;----------------------------------------------------------------------
  264. CHG_COMM    PROC    NEAR
  265.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  266.         MOV    BL,PORT_SELECT    ;Look at current port
  267.         XOR    BH,BH
  268.         SHL    BX,1
  269.         MOV    DX,ES:[BX]    ;Get the card address
  270.         ADD    DX,3        ;Point to line control
  271.         MOV    AH,ITEM_SELECT
  272.         DEC    AH        ;Changing baudrate?
  273.         JZ    CHG_BAUD
  274.         DEC    AH        ;Doing parity change?
  275.         JZ    CHG_PARITY
  276.         DEC    AH        ;Changing data bits
  277.         JZ    CHG_DATA_BITS
  278.         DEC    AH        ;Changing stop bits
  279.         JZ    CHG_STOP_BITS
  280.         JMP    GET_A_KEY
  281. CHG_BAUD:
  282.         CALL    READ_SET_BPS    ;Read current baudrate
  283.         CMP    CL,1
  284.         JNE    LOWER_BAUD    ;Going up?
  285.         CMP    BX,3        ;At 38400 bps?
  286.         JNE    SHIFT_DOWN
  287.         INC    BX        ;This is to get 57600 bps
  288. SHIFT_DOWN:
  289.         SHR    BX,1        ;Divide by two for new rate
  290.         OR    BX,BX        ;Is divisor zero yet?
  291.         JNZ    SET_NEW_BAUD
  292.         MOV    BX,384        ;Divisor for 300 bps
  293.         JMP    SHORT SET_NEW_BAUD
  294. LOWER_BAUD:
  295.         SHL    BX,1        ;Times two for new rate
  296.         CMP    BX,4        ;At 28800 bps?
  297.         JNE    SHIFT_UP
  298.         DEC    BX        ;This is to get 38400 bps
  299. SHIFT_UP:
  300.         CMP    BX,384        ;At 300 bps yet?
  301.         JBE    SET_NEW_BAUD
  302.         MOV    BX,1        ;Set divisor to 1
  303. SET_NEW_BAUD:
  304.         CALL    READ_SET_BPS    ;Set the new value
  305.         JMP    GET_A_KEY    ;And get another keystroke
  306. CHG_PARITY:
  307.         IN    AL,DX        ;Get current parity bits
  308.         MOV    BL,AL
  309.         AND    AL,11000111B    ;Erase old parity bits
  310.         SHR    BL,1        ;Shift parity bits over
  311.         SHR    BL,1
  312.         SHR    BL,1
  313. CHG_AGAIN:
  314.         ADD    BL,CL        ;Add in the change
  315.         AND    BL,00000111B
  316.         TEST    BL,00000001B
  317.         JNZ    PARITY_OK
  318.         TEST    BL,00000110B
  319.         JNZ    CHG_AGAIN    ;Skip meaningless settings
  320. PARITY_OK:
  321.         SHL    BL,1        ;Move parity bits back left
  322.         SHL    BL,1
  323.         SHL    BL,1
  324.         OR    AL,BL        ;Replace other starting bits
  325.         JMP    SHORT CHG_COMM_RET
  326. CHG_DATA_BITS:
  327.         IN    AL,DX        ;Get line control register
  328.         MOV    AH,AL        ;Save original line control
  329.         AND     AH,11111100B    ;Mask out old data bits
  330.         ADD    AL,CL
  331.         AND    AL,00000011B    ;These are the new data bits
  332.         OR    AL,AH        ;Put back other starting bits
  333.         JMP    SHORT CHG_COMM_RET
  334. CHG_STOP_BITS:
  335.         IN    AL,DX        ;Get line control register
  336.         XOR    AL,00000100B    ;Toggle the stop bit flag
  337. CHG_COMM_RET:
  338.         OUT    DX,AL        ;Set new line status
  339.         JMP    GET_A_KEY
  340. CHG_COMM    ENDP
  341.  
  342. ;----------------------------------------------------------------------
  343. ; REV_BAR turns the moving bar off and on
  344. ;----------------------------------------------------------------------
  345. BAR_SIZE    DB    0,6,5,1,1
  346. REV_BAR        PROC    NEAR
  347.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  348.         MOV    DH,ITEM_SELECT    ;Get selected item
  349.         OR    DH,DH        ;Are we in video mode row?
  350.         JZ    DOING_VIDEO    ;If yes then use video bar
  351.  
  352.         MOV    BL,DH        ;BL has item number
  353.         XOR    BH,BH
  354.         MOV    CL,BAR_SIZE[BX]    ;Get size of this bar
  355.         ADD    DH,5
  356.         MOV    AL,7
  357.         MUL    PORT_SELECT
  358.         ADD    AL,17
  359.         SUB    AL,CL
  360.         ADD    AL,LEFT_SIDE
  361.         MOV    DL,AL
  362. REV_LOOP:
  363.         CALL    READ_CHAR    ;Read current char at this position
  364.         MOV    AH,CH        ;Change the attribute
  365.         CALL    DISPLAY_CHAR    ;Then write the character again
  366.         DEC    CL
  367.         JNZ    REV_LOOP
  368. DONT_SHOW_IT:
  369.         RET
  370. DOING_VIDEO:
  371.         CMP    MODE_SELECT,19    ;Is this mode in normal range
  372.         JA    DONT_SHOW_IT    ;If not, just skip it
  373.         CALL    VIDEO_COLUMN    ;Find column for this mode
  374.         MOV    DH,15        ;Video is on row 15
  375.         MOV    CL,2        ;Size of bar is two columns
  376.         JMP    REV_LOOP
  377. REV_BAR        ENDP
  378.  
  379. ;----------------------------------------------------------------------
  380. ; VIDEO_COLUMN returns the column position for the selected video mode 
  381. ;----------------------------------------------------------------------
  382. COLUMN_DATA    DB    1,3,5,7,9,11,13,15,0,0,0,0,0,18,21,24,27,30,33,36
  383. VIDEO_COLUMN    PROC    NEAR
  384.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  385.         MOV    BL,MODE_SELECT    ;Get selected mode
  386.         XOR    BH,BH
  387.         MOV    DL,COLUMN_DATA[BX]
  388.         ADD    DL,LEFT_SIDE    ;Add in column of left side
  389.         RET
  390. VIDEO_COLUMN    ENDP
  391.  
  392. ;----------------------------------------------------------------------
  393. ; OPEN_WINDOW draws a box with the double line border
  394. ;----------------------------------------------------------------------
  395. OPEN_WINDOW    PROC    NEAR
  396.         ASSUME    CS:CSEG, DS:CSEG, ES:NOTHING
  397.         OR    DH,DH
  398.         JZ    TOP_LINE
  399.         MOV    AL," "
  400.         MOV    CX," "*256+" "
  401.         CALL    OPEN_LINE    ;Open a blank line
  402. TOP_LINE:
  403.         MOV    AL,201
  404.         MOV    CX,187*256+205
  405.         CALL    OPEN_LINE    ;Top line
  406. WIN_LOOP2:
  407.         MOV    AL,186
  408.         MOV    CX,186*256+" "
  409.         CALL    OPEN_LINE    ;Middle lines
  410.         DEC    COUNTER1
  411.         JNZ    WIN_LOOP2
  412.         MOV    AL,200
  413.         MOV    CX,188*256+205
  414.         CALL    OPEN_LINE    ;Bottom line
  415.         RET
  416. OPEN_WINDOW    ENDP
  417.  
  418. ;----------------------------------------------------------------------
  419. ; OPEN_LINE is used by OPEN_WINDOW to create one row of the window
  420. ;----------------------------------------------------------------------
  421. OPEN_LINE    PROC    NEAR
  422.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  423.         MOV    DL,LEFT_SIDE
  424.         CALL    SAVE_CHAR
  425.         MOV    COUNTER2,38
  426. MIDDLE_LOOP:
  427.         MOV    AL,CL
  428.         CALL    SAVE_CHAR
  429.         DEC    COUNTER2
  430.         JNZ    MIDDLE_LOOP
  431.         MOV    AL,CH
  432.         CALL    SAVE_CHAR
  433.         INC    DH
  434.         RET
  435. OPEN_LINE    ENDP
  436.  
  437. ;----------------------------------------------------------------------
  438. ; SAVE_CHAR stores a character from the screen and displays a new char
  439. ;----------------------------------------------------------------------
  440. SAVE_CHAR    PROC    NEAR
  441.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  442.         PUSH    AX        ;Save the new character
  443.         CALL    READ_CHAR    ;Read the existing character
  444.         CMP    GRAPH_TEXT,1
  445.         JE    MODE_TEXT1
  446.         MOV    AH,NORMAL    ;Use normal foreground color
  447. MODE_TEXT1:
  448.         MOV    DS:[DI],AX    ;And store it in the buffer
  449.         INC    DI
  450.         INC    DI
  451.         POP    AX        ;Get back new character
  452.         CMP    GRAPH_TEXT,1
  453.         JE    MODE_TEXT2
  454.         TEST    AL,10000000B    ;Is this a high bit character
  455.         JZ    MODE_TEXT2    ;If not, just continue
  456.         MOV    AL,"*"        ;If it is, reset it to "*"
  457. MODE_TEXT2:
  458.         CALL    DISPLAY_NORMAL    ;Put up the new character
  459.         RET
  460. SAVE_CHAR    ENDP
  461.  
  462. ;----------------------------------------------------------------------
  463. ; TTY_STRING displays an ASCII string terminated with a byte of zero
  464. ;----------------------------------------------------------------------
  465. TTY_STRING    PROC    NEAR
  466.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  467.         LODSB
  468.         OR    AL,AL
  469.         JZ    TTY_RET
  470.         CALL    DISPLAY_NORMAL
  471.         JMP    TTY_STRING
  472. TTY_RET:
  473.         RET
  474. TTY_STRING    ENDP
  475.  
  476. ;----------------------------------------------------------------------
  477. ; DISPLAY routines display a character using a BIOS function call
  478. ;---------------------------------------------------------------------
  479. DISPLAY_NORMAL    PROC    NEAR
  480.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  481.         MOV    AH,NORMAL
  482. DISPLAY_CHAR:
  483.         PUSH    BX
  484.         PUSH    CX
  485.         CALL    GET_CURS_ADDR    ;Get address of BIOS cursor
  486.         MOV    ES:[BX],DX    ;Tell BIOS where the cursor is
  487.         MOV    BL,AH        ;Get back the attribute
  488.         MOV    BH,ES:ACTIVE_PAGE ;Get active page
  489.         MOV    CX,1        ;Write 1 character
  490.         MOV    AH,9        ;Write character and attribute
  491.         INT    10H
  492.         POP    CX
  493.         POP    BX
  494.         INC    DL        ;Advance the cursor column
  495.         RET            ;Done writing the character
  496. DISPLAY_NORMAL    ENDP
  497.  
  498. ;----------------------------------------------------------------------
  499. ; READ_CHAR reads a character from the screen
  500. ;---------------------------------------------------------------------
  501. READ_CHAR    PROC    NEAR
  502.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  503.         CALL    GET_CURS_ADDR    ;Get address of BIOS cursor
  504.         MOV    ES:[BX],DX    ;Tell BIOS where the cursor is
  505.         MOV    BH,ES:ACTIVE_PAGE ;Get active page
  506.         MOV    AH,8        ;BIOS function to read character
  507.         INT    10H        ;Read the character/attribute
  508.         RET
  509. READ_CHAR    ENDP
  510.  
  511. ;----------------------------------------------------------------------
  512. ; GET_CURS_ADDR finds the address of the cursor for current video page
  513. ;---------------------------------------------------------------------
  514. GET_CURS_ADDR    PROC    NEAR
  515.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  516.         MOV    BL,ES:ACTIVE_PAGE ;Get the current page number
  517.         XOR    BH,BH        ;Convert to a word offset
  518.         SHL    BX,1        ;Times two for a word
  519.         ADD    BX,OFFSET CURSOR_POSN ;Add in base address
  520.         RET
  521. GET_CURS_ADDR    ENDP
  522.  
  523. ;---------------------------------------------------------------------
  524. YES_TXT        DB    "Yes",0
  525. NO_TXT        DB    " No",0
  526. NA_TXT        DB    "n/a",0
  527. NONE_TXT    DB    " None",0
  528. ODD_TXT        DB    "  Odd",0
  529. EVEN_TXT    DB    " Even",0
  530. SPACE_TXT    DB    "Space",0
  531. MARK_TXT    DB    " Mark",0
  532. PARITY_TABLE    DW    OFFSET ODD_TXT,   OFFSET EVEN_TXT
  533.         DW    OFFSET SPACE_TXT, OFFSET MARK_TXT
  534.  
  535. ;----------------------------------------------------------------------
  536. ; SHOW_PORTS displays the current settings of all comm ports
  537. ;----------------------------------------------------------------------
  538. SHOW_PORTS    PROC    NEAR
  539.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  540.         XOR    BX,BX
  541.         MOV    COUNTER1,BL    ;Start with first comm port
  542. PORT_LOOP:
  543.         MOV    AL,7        ;Seven columns per port column
  544.         MUL    BL
  545.         SHR    AL,1
  546.         MOV    CX,6*256+16    ;Row/column for first item
  547.         ADD    CL,LEFT_SIDE    ;Add in column of left edge
  548.         ADD    CL,AL        ;And shift over to correct column
  549.  
  550.         MOV    DX,ES:[BX]    ;Retrive the comm port address
  551.         MOV    BP,DX        ;And save it here
  552.         OR    DX,DX        ;Is there a card installed?
  553.         JNZ    GOT_CARD    ;If yes, display its status
  554.         MOV    SI,OFFSET NA_TXT
  555.         MOV    DX,CX        ;Get row/column for this entry
  556.         SUB    DL,2
  557.         CALL    TTY_STRING    ;Display "n/a" text
  558.         JMP    NEXT_PORT    ;And go on to next port
  559. GOT_CARD:
  560.         MOV    AL,"0"        ;Put a zero in bps column
  561.         MOV    DX,CX
  562.         CALL    DISPLAY_NORMAL    ;Display the zero
  563.         MOV    DX,BP
  564.         ADD    DX,3        ;Point to line control register
  565.         CALL    READ_SET_BPS    ;Read the current baud rate
  566.         PUSH    BX        ;Save it
  567.         CALL    READ_SET_BPS    ;Restore original baud settings
  568.         POP    BX        ;Now we have the bps in BX
  569.         OR    BX,BX        ;Is it set to zero?
  570.         JZ    NO_BPS_SET    ;If yes, just skip it
  571.         XOR    DX,DX
  572.         MOV    AX,11520
  573.         DIV    BX
  574.  
  575.         MOV    COUNTER2,6    ;Display five digits
  576.         PUSH    CX
  577.         MOV    SI,CX        ;Save cursor position
  578.         MOV    BX,10
  579.         MOV    DX,AX
  580.         XOR    AX,AX
  581. CHAR_LOOP:
  582.         MOV    CX,DX
  583.         XOR    DX,DX
  584.         DIV    BX
  585.         XCHG    AX,CX
  586.         DIV    BX
  587.         XCHG    AX,DX
  588.         ADD    AL,"0"        ;Convert this digit to ASCII
  589.         PUSH    DX
  590.         DEC    SI        ;Backup cursor position
  591.         MOV    DX,SI
  592.         CALL    DISPLAY_NORMAL    ;Display this digit
  593.         DEC    COUNTER2
  594.         POP    DX
  595.         MOV    AX,CX
  596.         OR    CX,DX
  597.         JNZ    CHAR_LOOP
  598.         MOV    DX,SI
  599. FILL_BLANKS:
  600.         DEC    DL
  601.         MOV    AL," "
  602.         CALL    DISPLAY_NORMAL
  603.         DEC    DL
  604.         DEC    COUNTER2
  605.         JNZ    FILL_BLANKS
  606.         POP    CX
  607. NO_BPS_SET:
  608.         MOV    DX,BP        ;Get back the port address
  609.         ADD    DX,3        ;Line control register
  610.         IN    AL,DX
  611.         PUSH    AX        ;Save starting status
  612.         MOV    SI,OFFSET NONE_TXT
  613.         TEST    AL,00001000B    ;Look at parity enable bit
  614.         JZ    NO_PARITY
  615.         AND    AX,00110000B    ;Look at parity bits
  616.         SHR    AX,1
  617.         SHR    AX,1
  618.         SHR    AX,1
  619.         MOV    SI,AX
  620.         MOV    SI,PARITY_TABLE[SI]
  621. NO_PARITY:
  622.         MOV    DX,CX
  623.         SUB    DL,4
  624.         ADD    DH,1
  625.         CALL    TTY_STRING    ;Display parity status
  626.  
  627.         POP    AX
  628.         PUSH    AX        ;Get line control status again
  629.         AND    AL,00000011B    ;Look at data bits
  630.         ADD    AL,35H        ;Convert it to ASCII code
  631.         MOV    DX,CX
  632.         ADD    DH,2
  633.         CALL    DISPLAY_NORMAL
  634.  
  635.         POP    DX
  636.         PUSH    DX        ;Get line control status again
  637.         MOV    AL,"1"        ;Assume one stop bit
  638.         TEST    DL,00000100B    ;Are two stop bits used?
  639.         JZ    ONE_STOP
  640.         INC    AL
  641. ONE_STOP:
  642.         MOV    DX,CX
  643.         ADD    DH,3
  644.         CALL    DISPLAY_NORMAL
  645.  
  646.         MOV    DX,BP
  647.         ADD    DX,6        ;Point to modem status register
  648.         IN    AL,DX
  649.         MOV    SI,OFFSET NO_TXT
  650.         TEST    AL,00100000B    ;Is bit five set?
  651.         JZ    NO_DSR        ;If not, DSR is not on
  652.         MOV    SI,OFFSET YES_TXT
  653. NO_DSR:
  654.         MOV    DX,CX
  655.         ADD    DH,4
  656.         SUB    DL,2
  657.         CALL    TTY_STRING
  658.  
  659.         POP    AX
  660.         MOV    DX,BP        ;Get back the card adress
  661.         ADD    DX,3
  662.         OUT    DX,AL        ;Restore the line status register
  663. NEXT_PORT:
  664.         MOV    BL,COUNTER1
  665.         XOR    BH,BH
  666.         INC    BX
  667.         INC    BX
  668.         CMP    BL,8        ;Do four comm ports
  669.         JAE    PORT_DONE
  670.         MOV    COUNTER1,BL
  671.         JMP    PORT_LOOP
  672. PORT_DONE:
  673.         RET
  674. SHOW_PORTS    ENDP
  675.  
  676. ;----------------------------------------------------------------------
  677. ; READ_SET_BPS reads the current baud rate and sets a new one
  678. ;----------------------------------------------------------------------
  679. READ_SET_BPS    PROC    NEAR
  680.         ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING
  681.         IN    AL,DX        ;Read the line status register
  682.         MOV    AH,AL        ;Save initial line status
  683.         MOV    AL,80H
  684.         OUT    DX,AL
  685.         SUB    DX,3        ;Get to low byte of divisor
  686.         IN    AL,DX
  687.         XCHG    BL,AL
  688.         OUT    DX,AL        ;Write the high byte of divisor
  689.         INC    DX        ;Get to high byte of divisor
  690.         IN    AL,DX
  691.         XCHG    BH,AL
  692.         OUT    DX,AL        ;Write the high byte of divisor
  693.         INC    DX        ;Back to line status register
  694.         INC    DX
  695.         MOV    AL,AH        ;Get back original line status
  696.         OUT    DX,AL        ;And restore it
  697.         RET
  698. READ_SET_BPS    ENDP
  699.  
  700. ;----------------------------------------------------------------------
  701. COLOR_TABLE    DB    1,2,1,2,2,1,1,3,2,2,3,2,1,2,2
  702. RES_TABLE    DW    OFFSET RES_1, OFFSET RES_1, OFFSET RES_2
  703.         DW    OFFSET RES_2, OFFSET RES_3, OFFSET RES_3
  704.         DW    OFFSET RES_4, OFFSET RES_2, OFFSET RES_5
  705.         DW    OFFSET RES_4, OFFSET RES_6, OFFSET RES_6
  706.         DW    OFFSET RES_7, OFFSET RES_7, OFFSET RES_5
  707. RES_1        DB    "25x40  ",0
  708. RES_2        DB    "25x80  ",0
  709. RES_3        DB    "320x200",0
  710. RES_4        DB    "640x200",0
  711. RES_5        DB    "320x200",0
  712. RES_6        DB    "640x350",0
  713. RES_7        DB    "640x480",0
  714. TEXT_TXT    DB    "Text ",0
  715. GRAPH_TXT    DB    "Graph",0
  716. COLOR_TXT    DB    "Color",0
  717. MONO_TXT    DB    "Mono ",0
  718. BW_TXT        DB    "B/W  ",0
  719.  
  720. ;----------------------------------------------------------------------
  721. ; SHOW_MODE displays the selected video mode number and resolution
  722. ;----------------------------------------------------------------------
  723. SHOW_MODE    PROC    NEAR
  724.         ASSUME    CS:CSEG, DS:CSEG, ES:BIOS_SEG
  725.         MOV    BL,MODE_SELECT    ;Get selected mode
  726.         MOV    DH,14        ;Put text on row 14
  727.         MOV    DL,LEFT_SIDE
  728.         ADD    DL,9
  729.  
  730.         MOV    AL,BL        ;Current mode into AL
  731.         MOV    CL,10
  732.         XOR    AH,AH
  733.         DIV    CL        ;Divide by 10
  734.         MOV    BH,AH        ;Save remainder for next digit
  735.         OR    AL,AL        ;Is first digit a zero?
  736.         JNZ    TWO_DIGITS    ;If not, display it normally
  737.         MOV    AL," " - "0"    ;Make first digit a space
  738. TWO_DIGITS:
  739.         ADD    AL,"0"        ;Convert digit to ASCII
  740.         CALL    DISPLAY_NORMAL    ;First digit of mode number
  741.         MOV    AL,BH
  742.         ADD    AL,"0"
  743.         CALL    DISPLAY_NORMAL    ;Second digit of mode number
  744.         CMP    BL,19        ;Is this mode in table?
  745.         JA    NOT_IN_TABLE
  746.         ADD    DL,3        ;Skip three spaces
  747.         XOR    BH,BH
  748.         MOV    SI,OFFSET TEXT_TXT
  749.         CMP    BL,7
  750.         JE    TEXT_MODE
  751.         JB    NOT_EGA_MODE
  752.         SUB    BL,5
  753. NOT_EGA_MODE:
  754.         CMP    BL,3
  755.         JBE    TEXT_MODE
  756.         MOV    SI,OFFSET GRAPH_TXT
  757. TEXT_MODE:
  758.         CALL    TTY_STRING    ;Show text/graph mode
  759.         INC    DL        ;Skip a space
  760.         MOV    AL,COLOR_TABLE[BX]
  761.         MOV    SI,OFFSET BW_TXT
  762.         DEC    AL
  763.         JZ    SHOW_COLOR
  764.         MOV    SI,OFFSET COLOR_TXT
  765.         DEC    AL
  766.         JZ    SHOW_COLOR
  767.         MOV    SI,OFFSET MONO_TXT
  768. SHOW_COLOR:
  769.         CALL    TTY_STRING    ;Show color/bw mode selected
  770.         INC    DL        ;Skip a space
  771.         SHL    BX,1
  772.         MOV    SI,RES_TABLE[BX]
  773.         CALL    TTY_STRING    ;Display resolution of this mode
  774. NOT_IN_TABLE:
  775.         RET
  776. SHOW_MODE    ENDP
  777.  
  778. ;----------------------------------------------------------------------
  779. ; Interrupt 09 routine.  watch for trigger key to pop up.
  780. ;----------------------------------------------------------------------
  781. NEWINT09    PROC    FAR
  782.         ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING
  783.         STI            ;Allow other interrupts
  784.         PUSHF
  785.         PUSH    AX        ;Must save processor state
  786.         IN    AL,60H        ;Get the scan code
  787.         CMP    AL,HOTKEY    ;Is it the hot key?
  788.         JE    TRIGGER        ;If yes, check the mask
  789. INT09_EXIT:    POP    AX        ;Restore the processor state
  790.         POPF
  791.         JMP    CS:OLDINT09    ;Continue with ROM routine
  792. TRIGGER:    MOV    AH,2        ;Get keyboard status
  793.         INT    16H        ;BIOS keyboard service
  794.         AND    AL,0FH        ;Test only for shift keys
  795.         CMP    AL,SHIFT_MASK    ;Does it match out combination?
  796.         JNE    INT09_EXIT    ;If not, ignore it
  797.         CMP    CS:BUSY_FLAG,0    ;Is SETMODE already active?
  798.         JNZ    INT09_EXIT    ;If active, then exit
  799.         INC    CS:BUSY_FLAG    ;Its active now
  800.  
  801.         IN    AL,61H        ;These instructions reset KB
  802.         MOV    AH,AL
  803.         OR    AL,80H
  804.         OUT    61H,AL
  805.         MOV    AL,AH
  806.         JMP    SHORT KB_DELAY
  807. KB_DELAY:
  808.         OUT    61H,AL
  809.         CLI
  810.         MOV    AL,20H
  811.         OUT    20H,AL        ;Reset the interrupt controller
  812.         STI
  813.  
  814.         PUSH    BX        ;Must preserve all registers
  815.         PUSH    CX
  816.         PUSH    DX
  817.         PUSH    BP
  818.         PUSH    SI
  819.         PUSH    DI
  820.         PUSH    DS
  821.         PUSH    ES
  822.         PUSH    CS
  823.         POP    DS        ;Set DS to CSEG
  824.         MOV    AX,BIOS_SEG    ;ES points to BIOS data area
  825.         MOV    ES,AX
  826.         ASSUME    DS:CSEG, ES:BIOS_SEG
  827.         CALL    SETMODE        ;Do the window
  828.         DEC    BUSY_FLAG
  829.         POP    ES        ;Restore all registers
  830.         POP    DS
  831.         ASSUME    DS:NOTHING, ES:NOTHING
  832.         POP    DI
  833.         POP    SI
  834.         POP    BP
  835.         POP    DX
  836.         POP    CX
  837.         POP    BX
  838.         POP    AX
  839.         POPF
  840.         IRET            ;Now were all done
  841. NEWINT09    ENDP
  842.  
  843. ;--------------------------------------------------------------------
  844. ; Here is the code used to initialize setmode
  845. ;--------------------------------------------------------------------
  846.         ASSUME    CS:CSEG, DS:CSEG, ES:CSEG
  847. EVEN                        ;Align the buffer
  848. WINDOW_BUFFER    LABEL    BYTE
  849. INITIALIZE:
  850.         MOV    DX,OFFSET COPYRIGHT    ;Do first half of copyright
  851.         MOV    AH,9
  852.         INT    21H
  853.  
  854.         MOV    AX,1A00H    ;Read display combination code
  855.         INT    10H
  856.         CMP    AL,1AH        ;Is VGA or MCGA present?
  857.         JNE    NO_VGA
  858.         MOV    AH,00100000B    ;Set bit for MCGA adapter
  859.         CMP    BL,0BH        ;Is it model 30 with mono?
  860.         JE    SET_BITS
  861.         CMP    BL,0CH        ;Is it model 30 with color?
  862.         JE    SET_BITS
  863.         MOV    AH,00010000B    ;Set bit for VGA adapter
  864.         CMP    BL,7        ;Is it VGA mono?
  865.         JE    SET_BITS
  866.         CMP    BL,8        ;Is it VGA color?
  867.         JE    SET_BITS
  868. NO_VGA:
  869.         XOR    DH,DH
  870.         MOV    AH,0B8H        ;Look for a color adapter
  871.         CALL    LOOK_FOR_CARD
  872.         JNE    NO_COLOR
  873.         OR    DH,00000010B    ;Set bit for color adapter
  874. NO_COLOR:
  875.         MOV    AH,0B0H        ;Look for mono adapter
  876.         CALL    LOOK_FOR_CARD
  877.         JNE    NO_MONO
  878.         OR    DH,00000001B    ;Set bit for mono adapter
  879. NO_MONO:
  880.         MOV    ADAPTER_FLAGS,DH
  881.         MOV    AH,12H
  882.         MOV    BL,10H        ;BIOS get EGA info function
  883.         INT    10H
  884.         CMP    BL,10H        ;Did BL change?
  885.         JE    NOT_EGA        ;If not, no EGA present
  886.  
  887.         PUSH    ES
  888.         MOV    AX,BIOS_SEG
  889.         MOV    ES,AX
  890.         ASSUME    ES:BIOS_SEG
  891.         MOV    AH,00000100B    ;Set bit for EGA color
  892.         TEST    ES:EGA_INFO,00000010B ;Is an EGA mono attached?
  893.         POP    ES
  894.         ASSUME    ES:CSEG
  895.         JZ    SET_BITS
  896.         MOV    AH,00001000B    ;Set bit for EGA mono only
  897. SET_BITS:
  898.         OR    ADAPTER_FLAGS,AH
  899. NOT_EGA:        
  900. ; Search for an previously installed copy of setmode
  901.         NOT    BYTE PTR START    ;Modify to avoid false match
  902.         XOR    BX,BX        ;Start search at segment zero
  903.         MOV    AX,CS        ;Compare to this code segment
  904. NEXT_SEGMENT:
  905.         INC    BX        ;Look at next segment
  906.         CMP    AX,BX        ;Until reaching this code segment
  907.         MOV    ES,BX
  908.         JE    NOT_INSTALLED
  909.         MOV    SI,OFFSET START    ;Setup to compare strings
  910.         MOV    DI,SI
  911.         MOV    CX,16        ;16 bytes must match
  912.         REP    CMPSB        ;Compare DS:SI to ES:DI
  913.         OR    CX,CX        ;Did the strings match?
  914.         JNZ    NEXT_SEGMENT    ;If no match, try next segment
  915.         MOV    DX,OFFSET INSTALLED_MSG
  916. ERR_EXIT:    MOV    AH,9        ;DOS display string service
  917.         INT    21H        ;Display error message
  918.         MOV    AX,4C01H    ;Return error code
  919.         INT    21H        ;Exit to DOS
  920. NOT_INSTALLED:
  921.         ASSUME    ES:NOTHING
  922.                MOV    AX,3509H    ;Get keyboard vector
  923.         INT    21H
  924.         MOV    WORD PTR [OLDINT09],  BX  ;Save segment
  925.         MOV    WORD PTR [OLDINT09+2],ES  ;Save offset
  926.         MOV    DX,OFFSET NEWINT09
  927.         MOV    AX, 2509H
  928.         INT    21H        ;DOS function to change vector
  929.  
  930. ;----------------------------------------------------------------------
  931. ; Deallocate our copy of the enviornment.  Terminate
  932. ; and stay resident. Leave code and space for buffer resident.
  933. ;----------------------------------------------------------------------
  934.  
  935.         MOV    AX,DS:[002CH]    ;Get segnemt of enviornment
  936.         MOV    ES,AX        ;Put it into ES
  937.         MOV    AH,49H        ;Release allocated memory
  938.         INT    21H
  939.         MOV    DX,OFFSET WINDOW_BUFFER + 40*18*2 + 15
  940.         MOV    CL,4        ;Shift four to divide by 16
  941.         SHR    DX,CL        ;Convert size to paragraphs
  942.         MOV    AX,3100H    ;Return success status
  943.         INT    21H
  944.  
  945. ;---------------------------------------------------------------------
  946. ; This routine examines memory to look for a display card.
  947. ;---------------------------------------------------------------------
  948. LOOK_FOR_CARD    PROC    NEAR
  949.         ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING
  950.         XOR    SI,SI        ;Look at offset zero
  951.         PUSH    DS
  952.         XOR    AL,AL
  953.         MOV    DS,AX        ;Load the segment register
  954.         MOV    CH,[SI]        ;Store the initial value
  955.         MOV    AL,55H
  956.         MOV    [SI],AL        ;Write pattern of ones and zeros
  957.         JMP    SHORT DELAY    ;A short delay 
  958. DELAY:
  959.         MOV    AH,[SI]        ;Read the byte we just wrote
  960.         MOV    [SI],CH        ;Restore the initial value
  961.         POP    DS
  962.         CMP    AL,AH        ;Did it match?
  963.         RET
  964. LOOK_FOR_CARD    ENDP
  965. CSEG        ENDS
  966.         END    START
  967.